package hehe.validation.base;

import hehe.validation.Validation;
import hehe.validation.validator.Validator;

import javax.swing.plaf.PanelUI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 验证规则类
 *<B>说明：</B>
 *<pre>
 * 略
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class Rule
{

    public static final String AND_OPERATOR = "and";
    public static final String OR_OPERATOR = "OR";
    public static final String MESSAGE_ATTR = "message";
    public static final String NON_ATTR = "non";
    public static final String ONEMPTY_ATTR = "onEmpty";
    public static final String NAME_VALIDATOR_ANNOTATION = "name";
    public static final String TIP_VALIDATOR_ANNOTATION = "tip";
    public static final String SCENE_VALIDATOR_ANNOTATION = "scene";
    public static final String NON_VALIDATOR_ANNOTATION = "non";
    public static final String ONEMPTY_VALIDATOR_ANNOTATION = "onEmpty";
    public static final String GOON_VALIDATOR_ANNOTATION = "goOn";




    /**
     * 验证管理对象
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Validation validation;

    /**
     * 属性名列表
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected List<String> attrs = new ArrayList<>();

    /**
     * 验证类型
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected List<Verify> validators = new ArrayList<>();

    /**
     * 与或操作符
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected String operator = AND_OPERATOR;

    /**
     * 当验证错误是是否继续验证
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected boolean goOn = true;

    /**
     * 当验证错误是是否继续验证
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected List<String> scenes = new ArrayList<>();

    /**
     * 错误消息
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String message;

    public Rule(){}

    public Rule(String attr)
    {
        this.attrs.add(attr);
    }

    public Rule(String attr,String validatorName)
    {
        this.attrs.add(attr);
        this.add(validatorName);
    }

    public Rule(String attr,Verify... verifys)
    {
        this.attrs.add(attr);
        for (Verify verify:verifys) {
            this.add(verify);
        }
    }

    /**
     * 设置提示信息
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Rule tip(String msg)
    {
        this.message = msg;
        return this;
    }

    /**
     * 设置场景
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Rule scene(String... scenes)
    {
        for (String scene:scenes) {
            this.scenes.add(scene);
        }

        return this;
    }

    /**
     * 设置验证管理类
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void setValidation(Validation validation)
    {
        this.validation = validation;
    }

    public Rule on(String attr,String validator)
    {
        return this.validation.on(attr,validator);
    }

    public Rule on(String attr,Verify... verifys)
    {
        return this.validation.on(attr,verifys);
    }

    /**
     * 当验证未通过时,是否继续验证其他参数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public boolean goOn()
    {
        return this.goOn;
    }

    /**
     * 设置验证的属性
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public Rule attr(String ... attrs)
    {
        for (String attr:attrs) {
            this.attrs.add(attr);
        }

        return this;
    }

    /**
     * 获取设置的验证属性名称列表
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public List<String> getAttrs()
    {
        return this.attrs;
    }

    /**
     * 添加验证类型
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public Rule add(String validatorName)
    {
        this.validators.add(new Verify(validatorName));
        return this;
    }

    /**
     * 添加验证类型
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public Rule add(Verify verify)
    {
        this.validators.add(verify);
        return this;
    }

    /**
     * 验证规则
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     * @return boolean
     */
    public boolean validateRule(Map<String,Object> attributes)
    {
        // 遍历验证属性
        Validator validator;
        List<ValidateResult> results = new ArrayList<>();
        // 读取对应的属性值
        Map<String,Object> attrsValue = this.buildValidateAttrs(attributes);

        // 遍历验证规则
        for (Verify verify:this.validators) {
            // 实例化验证类
            verify.setValidation(this.validation);
            validator = verify.createValidator();
            if (validator == null) {
                return false;
            }

            results.add(validator.validateValues(attrsValue));
        }

        return this.parseValidateResult(results);
    }

    /**
     * 解析验证结果
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    private boolean parseValidateResult(List<ValidateResult> results)
    {
        if (this.operator.equals(AND_OPERATOR)) {
            return this.parseAndValidateResult(results);
        } else {
            return this.parseOrValidateResult(results);
        }
    }

    /**
     * 解析and验证结果
     *<B>说明：</B>
     *<pre>
     * 方法详细描述
     *</pre>
     */
    protected boolean parseAndValidateResult(List<ValidateResult> results)
    {
        // 遍历验证结果
        boolean validateStatus = true;

        for (ValidateResult result:results) {
            if (!result.isPass()) {
                // 验证未通过
                validateStatus = false;
                if (this.message != null) {
                    this.validation.addError(new Error(this.message));
                } else {
                    this.validation.addError(new Error(result.getMessage()));
                }

                break;
            }
        }

        return validateStatus;
    }

    /**
     * 解析or验证结果
     *<B>说明：</B>
     *<pre>
     * 方法详细描述
     *</pre>
     */
    protected boolean parseOrValidateResult(List<ValidateResult> results)
    {
        // 遍历验证结果
        boolean validateStatus = false;

        for (ValidateResult result:results) {
            if (result.isPass()) {
                // 验证未通过
                validateStatus = true;
                if (this.message != null) {
                    this.validation.addError(new Error(this.message));
                } else {
                    this.validation.addError(new Error(result.getMessage()));
                }

                break;
            }
        }

        return validateStatus;
    }

    /**
     * 构建验证属性值
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    private Map<String,Object> buildValidateAttrs(Map<String,Object> attributes)
    {
        Map<String,Object> attrsValue = new HashMap<>();
        for (String attr:this.attrs) {
            if (attributes.containsKey(attr)) {
                attrsValue.put(attr,attributes.get(attr));
            } else {
                attrsValue.put(attr,null);
            }
        }

        return attrsValue;
    }

    /**
     * 验证规则是否可用
     *<B>说明：</B>
     *<pre>
     * 验证当前验证规则是否匹配传入的场景
     *</pre>
     * @param scenes 场景列表
     */
    public boolean isActive(String... scenes)
    {
        // 未设置场景,可用
        if (this.scenes.size() == 0) {
            return true;
        }

        // 传入场景null,在规则设置场景的情况下,可用推断出此规则适合当前场景
        if (scenes == null) {
            return false;
        }

        // 遍历验证传入场景
        for (String scene:scenes) {
            if (this.scenes.contains(scene)) {
                return true;
            }
        }

        return false;
    }

    public void and()
    {
        this.operator = AND_OPERATOR;
    }

    public void or()
    {
        this.operator = OR_OPERATOR;
    }

    public String toString()
    {
        return this.message + "," + this.validators.size();
    }

}
